package com.liang.pcc.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.liang.pcc.domain.AuthUser;
import com.liang.pcc.domain.ExcelFile;
import com.liang.pcc.excel.listener.*;
import com.liang.pcc.excel.model.BusParamInvestigation;
import com.liang.pcc.excel.model.EquipmentLineParam;
import com.liang.pcc.excel.model.TopologyData;
import com.liang.pcc.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;

@Slf4j
@RestController
@RequestMapping("/excel")
@RequiredArgsConstructor
public class ExcelController {

    private final BusParamService busParamService;
    private final EquipmentLineInfoService equipmentLineService;
    private final PowerDataService powerDataService;
    private final DeviceInfoService deviceInfoService;
    private final TopologyDataService topologyDataService;
    private final MeasurementPointService measurementPointService;
    private final ExcelFileService excelFileService;
    private final AuthUserService userService;

    private final ProcedureService procedureService;
    private final BusParamAsyncService busParamAsyncService;

    @Autowired
    @Qualifier("taskExecutor")
    private Executor taskExecutor;

    @PostMapping("/read")
    public void read(@RequestParam("file") MultipartFile file) throws Exception {
        // 插入Excel文件操作记录
        ExcelFile excelFile = ExcelFile.builder()
                .fileName(file.getOriginalFilename())
                .userAccount(StpUtil.getLoginId().toString())
                .operateTime(LocalDateTime.now())
                .build();
        excelFileService.save(excelFile);
        Long fileId = excelFile.getId();
        Long userId = userService.lambdaQuery().eq(AuthUser::getAccount, StpUtil.getLoginId().toString()).one().getId();
        log.info("当前文件ID：{}", fileId);
        log.info("开始读取Excel文件：{}", file.getOriginalFilename());

        // 定义同步锁（5个 Sheet）
        CountDownLatch latch = new CountDownLatch(5);

        // 显式指定文件类型为 XLSX
        try (ExcelReader excelReader = EasyExcel.read(file.getInputStream())
                .excelType(ExcelTypeEnum.XLSX) // 显式指定文件类型
                .build()) {
            // 创建监听器实例（绑定完成回调）
            MainLineDataListener mainLineListener = new MainLineDataListener(powerDataService, deviceInfoService, latch, fileId, userId);

            // 母线参数调研Sheet
            ReadSheet sheet1 = EasyExcel.readSheet(0)
                    .head(BusParamInvestigation.class)
                    .registerReadListener(new BusParamListener(busParamService, latch, fileId, userId))
                    .build();

            // 设备线路参数Sheet
            ReadSheet sheet2 = EasyExcel.readSheet(1)
                    .head(EquipmentLineParam.class)
                    .registerReadListener(new EquipmentLineParamListener(equipmentLineService, latch, fileId, userId))
                    .build();

            // 主变线路运行Sheet
            ReadSheet sheet3 = EasyExcel.readSheet(2)
                    .registerReadListener(mainLineListener)
                    .build();

            // 拓扑数据Sheet
            ReadSheet sheet4 = EasyExcel.readSheet(3)
                    .head(TopologyData.class)
                    .registerReadListener(new TopologyDataListener(topologyDataService, latch, fileId, userId))
                    .build();

            // 谐波电流Sheet
            ReadSheet sheet5 = EasyExcel.readSheet(4)
                    .headRowNumber(0)
                    .registerReadListener(new HarmonicCurrentListener(measurementPointService, latch, fileId, userId))
                    .build();

            // 执行读取操作
            excelReader.read(sheet1, sheet2, sheet3, sheet4, sheet5);
            latch.await();
            log.info("所有Sheet数据插入完成!");

            // --- 关键点：启动异步延迟任务 ---
            CompletableFuture.runAsync(() -> {
                try {
                    invokeProcedure(fileId, userId);
                } catch (Exception e) {
                    log.error("Error in read() method:", e);
                }
            }, taskExecutor);  // 使用自定义线程池
        }
    }

    private void invokeProcedure(Long fileId, Long userId) {
        // 单独处理第一条数据的独立可装
        procedureService.FixIndependentlyMountable(fileId);
        // 批量计算设备线路信息表的max_reverse_load_rate,max_occurrences,max_time,min_independent_mountable,min_occurrences,min_time
        procedureService.BatchUpdateEquipmentStats(fileId);
        // 计算拓扑结构表中设备的反向负载率和独立可装
        procedureService.updateTopologyData();
        // 设置母线与设备的上下级关系
        procedureService.insertTopologyData(fileId, userId);
        // 异步更新母线参数
        busParamAsyncService.asyncUpdateBusParams(fileId, userId);
        // 短路电流校验
        procedureService.syncShortCircuitData(userId, fileId);
        // 电压偏差校核
        procedureService.SyncVoltageDeviationCheck(userId, fileId);
        // 光伏承载力评估历史记录
        procedureService.SyncAndEvaluateAll(userId, fileId);
    }
}
